﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Collections.Generic
{
    public static class IEnumerableExtensions
    {
        public static string DominantValue(this IEnumerable<string> list)
        {
            Dictionary<string, int> index = new Dictionary<string, int>();

            while (list.Count() > 0)
            {
                string item = list.First();
                int nb = list.Count(i => i == item);
                index.Add(item, nb);
                list = list.Where(i => i != item).ToList();
            }

            int max = index.Max(kvp => kvp.Value);
            return index.First(kvp => kvp.Value == max).Key;
        }



        // IEnumerable<string>
        public static IEnumerable<string> GroupLike(this IEnumerable<string> list)
        {
            List<string> groups = new List<string>();
            while (list.Count() > 0)
            {
                string item = list.First();

                List<string> group = list.Where(i => item.Like(i)).ToList();
                groups.Add(group.DominantValue());

                list = list.Where(i => !item.Like(i)).ToList();
            }
            return groups;
        }
        public static string Join(this IEnumerable<string> me, string separator)
        {
            return string.Join(separator, me.ToArray());
        }



        public static bool Contains<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
        {
            return enumerable.Count(predicate) > 0;
        }

        public static IEnumerable<T> Except<T>(this IEnumerable<T> enumerable, T item)
        {
            if (item == null)
                return enumerable;

            Array array = Array.CreateInstance(typeof(T), 1);
            array.SetValue(item, 0);

            return enumerable.Except(array as IEnumerable<T>);
        }

        public static T MinValue<T>(this IEnumerable<T> enumerable, Func<T, float> predicate)
        {
            return enumerable.OrderBy(predicate).First();
        }
        public static T MaxValue<T>(this IEnumerable<T> enumerable, Func<T, float> predicate)
        {
            return enumerable.OrderBy(predicate).Last();
        }
        // TODO: Doc + overloads for decimal

        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> enumerable, Func<T, object> predicate)
        {
            List<T> result = new List<T>();

            foreach (T item in enumerable)
            {
                object value = predicate(item);
                if (!result.Contains(i => predicate(i) == value))
                    result.Add(item);
            }

            return result;
        }

        public static TimeSpan Sum<T>(this IEnumerable<T> enumerable, Func<T, TimeSpan> selector)
        {
            TimeSpan sum = TimeSpan.Zero;
            foreach (T item in enumerable)
                sum += selector(item);
            return sum;
        }
    }
}
